import DebugExt from "../base/DebugExt";

/** 通用文本信息存储扩展 */
export default class FileExt {

    /**
     * 写入玩家本地数据，默认关联玩家以及app信息
     * @param {string} key 数据键
     * @param {string | Object | number} data 数据对象(允许写入空数据,等同于移除读音键值)
     * @param {boolean} bindUser 是否关联游戏人物(默认关联)
     */
    static saveKeyData(key: string, data: string | Object | number, bindUser: boolean = true): void {
        // fixed key
        const keyFix = this.keyBindUserAndGame(key, bindUser);
        if (!keyFix || keyFix.length === 0)
            return;
        // 存入 local Storage
        if (!data) {
            DebugExt.info(`本地写入空数据 key: ${keyFix}， 执行删除键值操作。`);
            this.removeItem(keyFix);
        }
        else if (this.isObject(data)) {
            const dataStr = JSON.stringify(data);
            DebugExt.info(`本地写入数据对象 key: ${keyFix} value: ${dataStr}`);
            this.setItem(keyFix, dataStr);
        }
        else {
            DebugExt.info(`本地写入基础类型 key: ${keyFix} value: ${data}`);
            this.setItem(keyFix, data);
        }
    }

    /**
     * Removes key
     * 移除指定键值
     * @param {string} key 数据键
     * @param {boolean} bindUser 是否关联游戏人物(默认关联)
     */
    static removeKey(key: string, bindUser: boolean = true): void {
        const keyFix = this.keyBindUserAndGame(key, bindUser);
        if (!keyFix || keyFix.length === 0)
            return;
        // local Storage
        this.removeItem(keyFix);
        DebugExt.info(`删除本地数据 key: ${keyFix}`);
    }

    /**
     * 读取本地数据 (默认关联玩家以及app信息)
     * @param key 数据键
     * @param bindUser 是否关联游戏人物(默认关联)
     * @returns
     */
    static loadKeyObject(key: string, bindUser: boolean = true): any {
        const keyFix = this.keyBindUserAndGame(key, bindUser);
        if (!keyFix || keyFix.length === 0)
            return null;
        const objStr = this.getItem(keyFix);
        const data = objStr && objStr.length > 0 ? JSON.parse(objStr) : null;
        DebugExt.info(`读取本地文本数据信息: key: ${keyFix} value: ${objStr}`);
        return data;
    }

    /**
     * 读取本地数据 (默认关联玩家以及app信息)
     * @param key 数据键
     * @param def 默认值
     * @param bindUser 是否关联游戏人物(默认关联)
     * @returns number
     */
    static loadKeyNumber(key: string, def: number = 0, bindUser: boolean = true): number {
        const keyFix = this.keyBindUserAndGame(key, bindUser);
        if (!keyFix || keyFix.length === 0)
            return def;
        // 如果存储值为0，默认值不为0，特例处理
        const str = this.getItem(keyFix) || '';
        const value = str && str.length > 0 ? (Number(str) || def) : def;
        DebugExt.info(`读取本地文本数据信息: key: ${keyFix} value: ${value}`);
        return value;
    }

    /**
     * 读取本地数据 (默认关联玩家以及app信息)
     * @param key 数据键
     * @param def 默认值
     * @param bindUser 是否关联游戏人物(默认关联)
     * @returns string
     */
    static loadKeyString(key: string, def: string = "", bindUser: boolean = true): string {
        const keyFix = this.keyBindUserAndGame(key, bindUser);
        if (!keyFix || keyFix.length === 0)
            return def;
        // 如果存储值为0，默认值不为0，特例处理
        const str = this.getItem(keyFix) || def;
        DebugExt.info(`读取本地文本数据信息: key: ${keyFix} value: ${str}`);
        return str;
    }

    /**
     * Keys bind user and game
     * @param key 键值名
     * @param bindUser 是否关联玩家信息和app
     * @returns
     */
    private static keyBindUserAndGame(key: string, bindUser: boolean) {
        let fix = key.trim();
        if (!fix || fix.length === 0) {
            DebugExt.warn("Error: save or read Data, Key is Empty!");
            return "";
        }
        return key + (bindUser ? ("_uid_" + yy.myself.userID) : "") + ("_gid_" + yy.lobby.getMainGameID());
    }

    private static isObject(e: any) {
        return typeof e === "function" || (typeof e === "object" && e !== null);
    }

    private static setItem(key: string, data: any) {
        const keyfix = key && key.length > 0 ? key.trim() : '';
        if (keyfix.length > 0)
            cc.sys.localStorage.setItem(keyfix, data);
        else
            DebugExt.warn("setItem() called with invalid key: " + key);
    }

    private static getItem(key: string) {
        const keyfix = key && key.length > 0 ? key.trim() : '';
        if (keyfix.length > 0)
            return cc.sys.localStorage.getItem(keyfix);
        else {
            DebugExt.warn("getItem() called with invalid key: " + key);
            return null;
        }
    }

    private static removeItem(key: string) {
        const keyfix = key && key.length > 0 ? key.trim() : '';
        if (keyfix.length > 0)
            cc.sys.localStorage.removeItem(keyfix);
        else
            DebugExt.warn("removeItem() called with invalid key: " + key);
    }

}